﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.IO;
using SqlCeManager.Tools;
using DevExpress.XtraTreeList.Nodes;
using DevExpress.XtraTreeList;
using ProgNetComponentsDx.Options;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Docking;
using System.Data.SqlServerCe;
using ProgNetComponents.MDI;
using ProgNetComponentsDx.Browsers;
using ProgNetComponents.Classes;
using SqlCeManager.Setup;
using DevExpress.XtraEditors.Repository;

namespace SqlCeManager
{
    public partial class FormMain : XtraForm
    {
        private bool LockEvents = false;
        private List<ConnectionNode> Connections = new List<ConnectionNode>();
        private bool MergeMenus = false;
        private RepositoryItemTextEdit edit = new RepositoryItemTextEdit();

        public FormMain()
        {
            InitializeComponent();
            edit.Enter += new EventHandler(edit_Enter);
            treeConnections.DataSource = new RootNode(Connections);
            OptionCache.OptionChanged += new OptionChangedEventHandler(Instance_OptionChanged);
            MergeMenus = OptionCache.GetOptionValue(Init.InitFormOptionNames.Main.MergeMenus).AsBool();
            barManager1.MdiMenuMergeStyle = MergeMenus ? BarMdiMenuMergeStyle.Always : BarMdiMenuMergeStyle.Never;
        }

        void edit_Enter(object sender, EventArgs e)
        {
            BaseEdit ed = sender as BaseEdit;
            ed.Width = treeConnections.Width-treeConnections.IndicatorWidth - 80;
        }

        void Instance_OptionChanged(object optionId)
        {
            if (Init.InitFormOptionNames.Main.MergeMenus.IsTheSameKey(optionId))
            {
                bool val = OptionCache.GetOptionValue(optionId).AsBool();

                if (MergeMenus != val)
                {
                    MergeMenus = val;
                    barManager1.MdiMenuMergeStyle = val ? BarMdiMenuMergeStyle.Always : BarMdiMenuMergeStyle.Never;
                    if (MergeMenus)
                    {
                        barManager1.MergeBars("Tools");
                    }
                    else
                    {
                        barManager1.UnMergeBars("Tools");
                    }
                }
            }
        }

        #region connection panel
        private void dockPanelConnections_ClosedPanel(object sender, DockPanelEventArgs e)
        {
            LockEvents = true;
            bbiConnections.Checked = false;
            LockEvents = false;
        }

        private void bbiConnections_CheckedChanged(object sender,ItemClickEventArgs e)
        {
            if (!LockEvents)
            {
                if (bbiConnections.Checked)
                    dockPanelConnections.Show();
                else
                    dockPanelConnections.Close();
            }
        }

        
        #endregion

        #region Connection popup menu
        private void PreparePopUpMenu()
        {
            bbiDropTable.Visibility =
                bbiShowData.Visibility =
                bbiEditTable.Visibility =
                bbiDropTable.Visibility =
                bbiCopySchema.Visibility = VisibleForTable();

            bbiRefresh.Visibility = Connections.Count > 0 ? BarItemVisibility.Always : BarItemVisibility.Never;

            bbiCreateTable.Visibility =
                bbiCloseConnection.Visibility =
                bsiScripts.Visibility =
                bbiQuery.Visibility =
            bbiImportData.Visibility =
            bsiSchemaUpdate.Visibility = 
            bbiZmiany.Visibility = VisibleForConnection();
        }

        private BarItemVisibility VisibleForTable()
        {
            TableNode t = GetTableNode();
            if (t != null)
                return BarItemVisibility.Always;
            return BarItemVisibility.Never;
        }
        private BarItemVisibility VisibleForConnection()
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
                return BarItemVisibility.Always;
            return BarItemVisibility.Never;
        }

        private void treeConnections_MouseDown(object sender, MouseEventArgs e)
        {
            TreeListHitInfo info = treeConnections.CalcHitInfo(e.Location);
            if (info != null)
            {
                treeConnections.FocusedNode = info.Node;
            }
            if (e.Button == MouseButtons.Right)
            {
                PreparePopUpMenu();
                popupMenu1.ShowPopup(Control.MousePosition);
            }
        }
        
        private ConnectionNode GetConnectionNode()
        {
            ConnectionNode n = null;
            if (treeConnections.FocusedNode != null)
            {
                object o = treeConnections.GetDataRecordByNode(treeConnections.FocusedNode);
                if (o != null)
                {
                    if (o is ConnectionNode)
                        n = o as ConnectionNode;
                    else if (o is TableNode)
                        n = (o as TableNode).Connection;
                    else if (o is ColumnNode)
                        n = (o as ColumnNode).Table.Connection;
                }
            }
            return n;
        }
        private TableNode GetTableNode()
        {
            TableNode n = null;
            if (treeConnections.FocusedNode != null)
            {
                object o = treeConnections.GetDataRecordByNode(treeConnections.FocusedNode);
                if (o != null)
                {
                    if (o is TableNode)
                        n = (o as TableNode);
                    else if (o is ColumnNode)
                        n = (o as ColumnNode).Table;
                }
            }
            return n;
        }
        #endregion

        #region child form events
        void f_NewTabSaved(object sender, NewTabSavedEventArgs e)
        {
            if (mdiHelper1.TryAddChild(sender as Form, e.TableName, e.Node))
            {
                (sender as Form).FormClosed += new FormClosedEventHandler(f_FormClosed);
            }
        }

        void f_FormClosed(object sender, FormClosedEventArgs e)
        {
            Form f = sender as Form;
            foreach (ConnectionNode n in Connections)
                if (n.OwnedForms.Contains(f))
                    n.OwnedForms.Remove(f);
        }
        #endregion

        #region tools
        private void OpenConnection(int id)
        {
            if (id > -1)
            {
                Browser b  = BrowserCache.GetBrowser(Init.InitFormBrowserNames.Glowna.Polaczenia);
                DataRow r = b.GetRowForValue(id);
                if (r != null)
                {
                    string name = r["STP_POL_NAZWA"].AsString();
                    string plik = r["STP_POL_PLIK"].AsString();
                    if (File.Exists(plik))
                    {
                        string connectionString = r["STP_POL_CONNECTION_STRING"].AsString();
                        ConnectionNode n = new ConnectionNode(name, connectionString, treeConnections);
                        n.IdPolaczenia = id;
                        Connections.Add(n);
                        treeConnections.RefreshDataSource();
                    }
                }
            }
        }
        #endregion

        #region popup
        private void bbiOpenConnection_ItemClick(object sender,ItemClickEventArgs e)
        {
            Tools.ConnectionForm f = new SqlCeManager.Tools.ConnectionForm();
            if (f.ShowDialog() == DialogResult.OK)
            {
                int id = f.Id;
                if (id > -1)
                {
                    OpenConnection(id);
                }
            }
            f.Dispose();
        }

        private void bbiEditTable_ItemClick(object sender,ItemClickEventArgs e)
        {
            TableNode t = GetTableNode();
            if (t!=null)
            {
                Form f = mdiHelper1.GetMdiChild<TableDefinitionForm>(t.TableName, t.Connection);

                if (f != null)
                {
                    if (!t.Connection.OwnedForms.Contains(f))
                    {
                        f.FormClosed += new FormClosedEventHandler(f_FormClosed);
                        t.Connection.OwnedForms.Add(f);
                    }
                }
            }
        }

        private void bbiCreateTable_ItemClick(object sender,ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                TableDefinitionForm f = new TableDefinitionForm("", n);
                f.NewTabSaved += new EventHandler<NewTabSavedEventArgs>(f_NewTabSaved);
                f.FormClosed+=new FormClosedEventHandler(f_FormClosed);
                n.OwnedForms.Add(f);
                f.MdiParent = this;
                f.Show();
            }
        }

        private void bbiCloseConnection_ItemClick(object sender,ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                if (this.ShowDxLngYNQuestionDialog("Q_CLOSE_CONNECTION") == DialogResult.Yes)
                {
                    Form[] forms = n.OwnedForms.ToArray();
                    foreach (Form f in forms)
                        f.Close();
                    Connections.Remove(n);
                    treeConnections.RefreshDataSource();
                }
            }
        }

        private void bbiShowData_ItemClick(object sender,ItemClickEventArgs e)
        {
            TableNode t = GetTableNode();
            if ( t != null)
            {
                Form f = mdiHelper1.GetMdiChild<TableDataForm>(t.TableName, t.Connection);

                if (f != null)
                {
                    if (!t.Connection.OwnedForms.Contains(f))
                    {
                        f.FormClosed += new FormClosedEventHandler(f_FormClosed);
                        t.Connection.OwnedForms.Add(f);
                    }
                }
            }
        }

        private void bbiRefresh_ItemClick(object sender,ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                string table = "";
                TableNode t = GetTableNode();
                if (t != null)
                    table = t.TableName;
                n.GetTable(table);
            }
        }

        private void bbiScriptNewWindow_ItemClick(object sender,ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            TableNode t = GetTableNode();
            if (n != null)
            {
                string table = "";
                string name = n.Name;
                if (t != null)
                {
                    table = t.TableName;
                    name += " [ " + table + " ]";
                }
                n.ScriptTools.GenerateCreateScripts = true;
                string script = n.ScriptTools.GetScripts(table).AsString("\nGO;\n");
                ScriptWindow s = new ScriptWindow(name, script);
                s.MdiParent = this;
                s.Show();
            }
        }
        private void bbiScriptsClipboard_ItemClick(object sender, ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            TableNode t = GetTableNode();
            if (n != null)
            {
                string table = "";
                if (t != null)
                    table = t.TableName;
                n.ScriptTools.GenerateCreateScripts = true;
                string script = n.ScriptTools.GetScripts(table).AsString(Constants.NewLineLinux + "GO;" + Constants.NewLineLinux + Constants.NewLineLinux) + Constants.NewLineLinux + "GO;";
                Clipboard.SetText(script);
                if (!OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Main.NieInformujOWygenerowaniuSkryptow))
                    this.ShowDxLngInfoDialog("SCRIPTS_CREATED");
            }
        }

        private void bbiDropTable_ItemClick(object sender, ItemClickEventArgs e)
        {
            TableNode t = GetTableNode();
            if (t != null)
            {
                if (this.ShowDxLngYNQuestionDialog("Q_DELETE_TABLE") == DialogResult.Yes)
                {
                    t.Connection.SchemaDataSet.TABLES.DeleteRows("TABLE_NAME = " + t.TableName.EscapeSql());
                    t.Connection.ScriptTools.GenerateCreateScripts = false;
                    List<string> l = t.Connection.ScriptTools.GetScripts(t.TableName);
                    try
                    {
                        t.Connection.ExecuteCommands(l);
                        t.Connection.Tables.Remove(t);
                        t = null;
                        treeConnections.RefreshDataSource();
                    }
                    catch (Exception ex)
                    {
                        this.ShowDxErrorDialog("Query:" + t.Connection.LastQuery + "\nException:" + ex.Message);
                    }
                }
            }
        }

        private void bbiQuery_ItemClick(object sender, ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                FormQuery f = new FormQuery(n);
                f.MdiParent = this;
                f.Show();
            }
        }
        private void bbiImportData_ItemClick(object sender, ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                string conStr = "";
                ConnectionForm ff = new ConnectionForm();
                if (ff.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    conStr = ff.ConnectionString;
                if (conStr.IsNotNull())
                {
                    ImportDataForm f = new ImportDataForm(conStr, n.ConnectionString);
                    f.MdiParent = this;
                    f.Show();
                }
            }
        }
        #endregion

        #region override

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            base.OnFormClosed(e);
            if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Main.PamietajPolaczenia))
            {
                string str = "";
                foreach (ConnectionNode n in Connections)
                {
                    str = str.AppendString(",") + n.IdPolaczenia.ToString();
                }
                OptionCache.SetOptionValue(Init.InitFormOptionNames.Main.OtwartePolaczenia, str, true);
            }
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Main.PamietajPolaczenia))
            {
                string[] connections = OptionCache.GetOptionStringValue(Init.InitFormOptionNames.Main.OtwartePolaczenia).Split(',');

               foreach (string con in connections)
               {
                   OpenConnection(con.AsInt(-1));
               }
            }
            System.Diagnostics.Process.GetCurrentProcess().BringWindowToFront();
        }
        #endregion

        private void bbiToolsOptions_ItemClick(object sender,ItemClickEventArgs e)
        {
            mdiHelper1.GetMdiChild(typeof(Options.OptionsForm));
        }

        private void treeConnections_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (treeConnections.FocusedNode != null)
                {
                    object o = treeConnections.GetDataRecordByNode(treeConnections.FocusedNode);
                    if (o != null)
                    {
                        if (o is TableNode)
                        {
                            bbiDropTable_ItemClick(null, null);
                        }
                        else if (o is ConnectionNode)
                        {
                            bbiCloseConnection_ItemClick(null, null);
                        }
                    }
                }
            }
            else if(e.Control && ((e.KeyCode & Keys.C) == Keys.C))
            {
                ConnectionNode n = GetConnectionNode();
                if (n != null)
                {
                    Clipboard.SetText(n.ConnectionString);
                }
            }
        }

        private void barManager1_Merge(object sender, BarManagerMergeEventArgs e)
        {
            barManager1.MergeBars(e.ChildManager, "Tools");
        }

        private void barManager1_UnMerge(object sender, BarManagerMergeEventArgs e)
        {
            barManager1.UnMergeBars(e.ChildManager, "Tools");
        }

        private void bbiCopySchema_ItemClick(object sender, ItemClickEventArgs e)
        {
            TableNode n = GetTableNode();
            if (n != null)
            {
                try
                {
                    ScriptTools.GetXmlDef(n.TableName, n.Connection.SchemaDataSet, true);
                    this.ShowDxInfoDialog("Schema zapisana w schowku.");
                }
                catch (Exception ex)
                {
                    ex.Log();
                    this.ShowDxErrorDialog("Błąd kopiowania.");
                }
            }
        }

        private void bbiSchemaUpdateNewWin_ItemClick(object sender, ItemClickEventArgs e)
        {
            GetUpdateSchemaScripts(UpdateScriptDest.Window);
        }

        private void bbiSchemaUpdateSchowek_ItemClick(object sender, ItemClickEventArgs e)
        {
            GetUpdateSchemaScripts(UpdateScriptDest.Clipboard);
        }

        private void bbiSchemaUpdateUpdate_ItemClick(object sender, ItemClickEventArgs e)
        {
            GetUpdateSchemaScripts(UpdateScriptDest.None);
        }
        private void GetUpdateSchemaScripts(UpdateScriptDest dest)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
            {
                string conStr = "";
                ConnectionForm ff = new ConnectionForm();
                if (ff.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    conStr = ff.ConnectionString;
                if (conStr.IsNotNull())
                {
                    ConnectionNode newCon = new ConnectionNode("", conStr, null);
                    List<string> scripts = new List<string>();
                    try
                    {
                        scripts = ScriptTools.GetSchemaUpdateScripts(n.SchemaDataSet, newCon.SchemaDataSet);
                        string script = scripts.AsString("\nGO;\n");
                        switch (dest)
                        {
                            case UpdateScriptDest.Clipboard:
                                Clipboard.SetText(script);
                                if (!OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Main.NieInformujOWygenerowaniuSkryptow))
                                    this.ShowDxLngInfoDialog("SCRIPTS_CREATED");
                                break;
                            case UpdateScriptDest.Window:
                                ScriptWindow s = new ScriptWindow(n.Name, script);
                                s.MdiParent = this;
                                s.Show();
                                break;
                            case UpdateScriptDest.None:
                                FormQuery f = mdiHelper1.GetMdiChildFull<FormQuery>(MdiOptions.DefaultNoRemember, n);
                                if (f != null)
                                    f.ExecuteQuery(script);
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.Log();
                        this.ShowDxErrorDialog("Błąd generowania skryptów");
                    }
                }
            }
        }

        private enum UpdateScriptDest
        {
            Window,
            Clipboard,
            None
        }

        private void bbiZmianyBazy_ItemClick(object sender, ItemClickEventArgs e)
        {
            Browser b = BrowserCache.GetBrowser(Init.InitFormBrowserNames.Glowna.Polaczenia);
            ObjectDialogResult dlg = b.ShowDialog();
            if (dlg.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                mdiHelper1.GetMdiChild<DbUpdate.FormDbUpdate>(dlg.Value.AsInt());
            }
        }

        private void bbiPolaczenia_ItemClick(object sender, ItemClickEventArgs e)
        {
            FormPolaczenia f = mdiHelper1.GetMdiChild<Setup.FormPolaczenia>();
            f.ConnectionsChanged -= new EventHandler(f_ConnectionsChanged);
            f.ConnectionsChanged += new EventHandler(f_ConnectionsChanged);
        }

        void f_ConnectionsChanged(object sender, EventArgs e)
        {
            Browser b = BrowserCache.GetBrowser(Init.InitFormBrowserNames.Glowna.Polaczenia);
            foreach (ConnectionNode n in Connections)
            {
                n.Name = b.GetRowForValue(n.IdPolaczenia)["STP_POL_NAZWA"].AsString();
            }
            treeConnections.RefreshDataSource();
        }

        public bool ConnectionOpened(int id)
        {
            foreach (ConnectionNode n in Connections)
                if (n.IdPolaczenia == id)
                    return true;
            return false;
        }

        private void bbiZmiany_ItemClick(object sender, ItemClickEventArgs e)
        {
            ConnectionNode n = GetConnectionNode();
            if (n != null)
                mdiHelper1.GetMdiChild<DbUpdate.FormDbUpdate>(n.IdPolaczenia);
        }

        private void treeConnections_ShowingEditor(object sender, CancelEventArgs e)
        {
            if (GetTableNode() == null)
                e.Cancel = true;
        }

        private void treeConnections_CustomDrawNodeImages(object sender, CustomDrawNodeImagesEventArgs e)
        {
            if (e.Node.Level == 0)
            {
                e.SelectImageIndex = 17;
            }
            else
            {
                e.SelectImageIndex = -1;
                //e.Graphics.DrawImage(this.commonImageCollectionFull1.Images[10], e.SelectRect);
            }
        }

        private void treeConnections_CustomDrawNodeCell(object sender, CustomDrawNodeCellEventArgs e)
        {
            object o = treeConnections.GetDataRecordByNode(e.Node);
            bool isColNode = false;
            if (o != null)
            {
                if (o is ColumnNode)
                    isColNode = true;
            }
            if (!isColNode)
            {
                if (e.Column == colComment)
                    e.Handled = true;
                else
                {
                    e.Graphics.DrawString(e.CellText, treeConnections.Font, e.Cache.GetSolidBrush(treeConnections.ForeColor), e.EditViewInfo.Bounds.Location);
                    e.Handled = true;
                }
            }
        }
        private void treeConnections_CustomNodeCellEdit(object sender, GetCustomNodeCellEditEventArgs e)
        {
            object o = treeConnections.GetDataRecordByNode(e.Node);
            if (!(o is ColumnNode))
            {
                e.RepositoryItem = edit;
            }
        }
    }
}
